Skip to content

anywidget-graph

Interactive graph visualization widget for Python notebooks.

GitHub PyPI

Overview

anywidget-graph provides interactive graph visualization powered by Sigma.js. Built on the anywidget framework, it works universally across Jupyter, Marimo, VS Code, Colab, and Databricks with support for multiple graph database backends.

Features

Multi-Backend Support

Backend Query Languages
Grafeo GQL, Cypher, SPARQL, Gremlin, GraphQL
Neo4j Cypher
ArangoDB AQL
LadybugDB Cypher
NetworkX Python API

Query Language Converters

Automatically converts query results from:

  • Cypher (Neo4j, Grafeo)
  • GQL (ISO standard)
  • SPARQL (RDF/semantic web)
  • Gremlin (TinkerPop)
  • GraphQL (JSON responses)
  • AQL (ArangoDB)

Interactivity

  • Pan, zoom, and navigate
  • Click nodes/edges to select
  • Expand/collapse neighbors
  • Multi-select paths
  • Export to PNG, SVG, JSON

Installation

uv add anywidget-graph

With optional backends:

uv add "anywidget-graph[networkx,neo4j]"

Quick Start

From Grafeo

from anywidget_graph import Graph
from grafeo import GrafeoDB

db = GrafeoDB()
db.execute("""
    INSERT (:Person {name: 'Alice'})-[:KNOWS]->(:Person {name: 'Bob'}),
           (:Person {name: 'Bob'})-[:KNOWS]->(:Person {name: 'Carol'})
""")

result = db.execute("MATCH (n)-[r]->(m) RETURN n, r, m")
graph = Graph.from_grafeo(result)
graph

From NetworkX

import networkx as nx
from anywidget_graph import Graph

G = nx.karate_club_graph()
widget = Graph.from_networkx(G)
widget

From Edge List

from anywidget_graph import Graph

nodes = [
    {"id": "1", "label": "Alice", "group": "person"},
    {"id": "2", "label": "Bob", "group": "person"},
    {"id": "3", "label": "Acme", "group": "company"},
]

edges = [
    {"source": "1", "target": "2", "label": "knows"},
    {"source": "2", "target": "3", "label": "works_at"},
]

widget = Graph(nodes=nodes, edges=edges)
widget

Styling

Node Styling

widget = Graph(
    nodes=nodes,
    edges=edges,
    node_color_by="group",
    node_size_by="degree",
    node_colors={
        "person": "#6366f1",
        "company": "#22c55e"
    }
)

Layout Algorithms

widget = Graph(
    nodes=nodes,
    edges=edges,
    layout="force",  # force, hierarchical, circular, grid
)

Event Handling

@widget.on_node_click
def handle_node_click(node_id, node_data):
    print(f"Clicked: {node_data['label']}")

@widget.on_edge_click
def handle_edge_click(edge_id, edge_data):
    print(f"Edge: {edge_data['label']}")

Configuration

widget = Graph(
    nodes=nodes,
    edges=edges,

    # Display
    show_labels=True,
    show_edge_labels=False,
    show_toolbar=True,
    dark_mode=True,

    # Layout
    layout="force",

    # Performance
    virtualize=True,  # For 1000+ nodes
)

Database Connections

Neo4j

from anywidget_graph import Graph
from anywidget_graph.backends import Neo4jBackend

backend = Neo4jBackend(
    uri="bolt://localhost:7687",
    user="neo4j",
    password="password"
)

widget = Graph(
    backend=backend,
    query="MATCH (n)-[r]->(m) RETURN n, r, m LIMIT 100"
)

ArangoDB

from anywidget_graph.backends import ArangoDBBackend

backend = ArangoDBBackend(
    host="localhost",
    database="mydb",
    username="root",
    password="password"
)

widget = Graph(
    backend=backend,
    query="FOR v, e IN 1..2 OUTBOUND 'nodes/1' edges RETURN {v, e}"
)

Notebook Compatibility

Works in any environment supporting anywidget:

  • JupyterLab / Jupyter Notebook
  • Marimo
  • VS Code Notebooks
  • Google Colab
  • Databricks

Requirements

  • Python 3.12+
  • Modern browser

License

Apache-2.0